#pragma once
#include <string>
#include <cstddef>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <odb/nullable.hxx>

/* ===================================================================
 *  在 C++ 中, 要使用 ODB 将类声明为持久化类, 需要包含 ODB 的核心头文件,
 *  并使用 #pragma db object 指令
 *  #pragma db object 指示 ODB 编译器将 person 类视为一个持久化类。
 * =================================================================== */

#include <odb/core.hxx>
typedef boost::posix_time::ptime ptime;

#pragma db object table("person")
class Person 
{
public:
    Person(const std::string &name, int age, const ptime 
    &update):
    name_(name), age_(age), update_(update){}
    void age(int val) { age_ = val; }
    int age() { return age_; }
    void name(const std::string& val) { name_ = val; }
    std::string name() { return name_; }
    void update(const ptime &update) { update_ = update; }
    std::string update()  { return boost::posix_time::to_simple_string(*update_);  }
private:
    // 将 odb::access 类作为 person 类的朋友。
    // 这是使数据库支持代码可访问默认构造函数和数据成员所必需的
    // 如果类具有公共默认构造函数和公共数据成员或数据成员的公共访问器和修饰符, 则不需要友元声明
    friend class odb::access;
    Person () {}
    // id_ 成员前面的 pragma 告诉 ODB 编译器, 以下成员是对象的标识符。auto 说明符指示它是数据库分配的 ID
    #pragma db id auto  // 表示 ID 字段将自动生成(通常是数据库中的主键)
    unsigned long id_;
    #pragma db column("user_age") type("SMALLINT UNSIGNED") default(20)  // 将该字段重命名/类型转换(需合理)
    unsigned short age_;
    #pragma db type("VARCHAR(32)") unique
    std::string name_;
    #pragma db type("TIMESTAMP") index
    odb::nullable<boost::posix_time::ptime> update_;    // odb::nullable<T> 可为空字段
};

/* ===============================================================================================
 *  将 ODB 编译指示组合在一起, 并放在类定义之后。它们也可以移动到一个单独的标头中, 使原始类完全保持不变
 *  #pragma db object(person)
 *  #pragma db member(person::name_) id
 *  完成后, 需要使用 odb 编译器将当前所写的代码生成数据库支持代码
 *  odb -d mysql --generate-query --generate-schema person.hxx
 *  如果用到了 boost 库中的接口, 则需要使用选项 : --profile boost/datetime
 *  
 *  odb -d mysql --generate-query --generate-schema --profile boost/date-time person.hxx
 * =============================================================================================== */